package com.maxlen.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maxlen.common.constant.AuthServerConstant;
import com.maxlen.common.utils.*;
import com.maxlen.member.constant.AllConstant;
import com.maxlen.member.dao.MemberDao;
import com.maxlen.member.entity.MemberEntity;
import com.maxlen.member.entity.vo.LoginVO;
import com.maxlen.member.entity.vo.UserRegisterVO;
import com.maxlen.member.feign.ThirdPartyFeignService;
import com.maxlen.member.service.MemberLevelService;
import com.maxlen.member.service.MemberService;
import com.maxlen.member.utils.CodeUtils;
import com.maxlen.member.utils.HttpRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    private MemberLevelService memberLevelService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ThirdPartyFeignService thirdPartyFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 判断用户名是否唯一
     * @param username
     * @return
     */
    @Override
    public R isExistUsername(String username) {
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getUsername, username));
        if(count > 0){
            return R.error(ResultCode.USER_REGISTER_USERNAME_EXIST);
        }else{
            return R.ok();
        }
    }

    /**
     * 判断手机号是否唯一
     * @param phone
     * @return
     */
    @Override
    public R isExistPhone(String phone) {
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getMobile, phone));
        if(count > 0){
            return R.error(ResultCode.USER_REGISTER_PHONE_EXIST);
        }else{
            return R.ok();
        }
    }

    /**
     * 判断邮箱是否唯一
     * @param email
     * @return
     */
    @Override
    public R isExistEmail(String email) {
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getEmail, email));
        if(count > 0){
            return R.error(ResultCode.USER_REGISTER_EMAIL_EXIST);
        }else{
            return R.ok();
        }
    }

    /**
     * 会员注册
     * @param userRegisterVO
     * @return
     */
    @Override
    public R register(UserRegisterVO userRegisterVO) {

        R existUsername = isExistUsername(userRegisterVO.getUsername());
        if(!existUsername.isOk()){
            return R.error(ResultCode.USER_REGISTER_USERNAME_EXIST);
        }

        R existPhone = isExistPhone(userRegisterVO.getPhone());
        if(!existPhone.isOk()){
            return R.error(ResultCode.USER_REGISTER_PHONE_EXIST);
        }

        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setUsername(userRegisterVO.getUsername());
        memberEntity.setNickname(userRegisterVO.getUsername());
        memberEntity.setMobile(userRegisterVO.getPhone());
        memberEntity.setPassword(new BCryptPasswordEncoder().encode(userRegisterVO.getPassword()));
        memberEntity.setLevelId(memberLevelService.getDefaultStatus());

        if(baseMapper.insert(memberEntity) > 0){
            return R.ok();
        }else{
            return R.error();
        }
    }

    /**
     * 登录
     * @param loginVO
     * @return
     */
    @Override
    public R login(LoginVO loginVO) {

        LambdaQueryWrapper<MemberEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MemberEntity::getUsername, loginVO.getUsername()).or().eq(MemberEntity::getMobile, loginVO.getUsername());
        MemberEntity memberEntity = baseMapper.selectOne(wrapper);
        if(ObjectUtils.isEmpty(memberEntity)){
           return R.error(ResultCode.USER_ACCOUNT_NOT_EXIST);
        }

        if(new BCryptPasswordEncoder().matches(loginVO.getPassword(), memberEntity.getPassword())){
            return R.ok()
                    .put("token", setJWTRedis(memberEntity.getId().toString(), memberEntity.getNickname()))
                    .put("name", memberEntity.getNickname())
                    .put("photo", memberEntity.getHeader());
        }else{
            return R.error(ResultCode.USER_CREDENTIALS_ERROR);
        }

    }

    /**
     * Gitee 登录
     * @param code
     * @return
     */
    @Override
    public R OAuthGiteeLogin(String code) {

        try{
            String post = new HttpRequest()
                    .addParam("code", code)
                    .addParam("grant_type", "authorization_code")
                    .addParam("client_id", "f5b50c234cc92628d36d19985c01920921dcabbfd5ada902a9edf01913129568")
                    .addParam("client_secret", "6858ba66977115656acef5702f52bc13aa17f849b9ab432eb7cd7d9247963d9c")
                    .addParam("redirect_uri", "http://localhost:9527/login")
                    .post("https://gitee.com/oauth/token");
            if(StringUtils.hasText(post)){
                String token = JSON.parseObject(post).get("access_token").toString();
                String user = new HttpRequest().addParam("access_token", token).get("https://gitee.com/api/v5/user");
                if(StringUtils.hasText(user)){
                    JSONObject jsonObject = JSON.parseObject(user);
                    String id = jsonObject.get("id").toString();

                    MemberEntity memberEntity = baseMapper.selectOne(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getGiteeId, id));
                    if(ObjectUtils.isEmpty(memberEntity)){
                        memberEntity = new MemberEntity();
                        String name = jsonObject.get("name").toString();
                        memberEntity.setGiteeId(id);
                        memberEntity.setNickname(name);
                        memberEntity.setLevelId(memberLevelService.getDefaultStatus());
                        baseMapper.insert(memberEntity);
                    }
                    return R.ok()
                            .put("token", setJWTRedis(memberEntity.getId().toString(), memberEntity.getNickname()))
                            .put("name", memberEntity.getNickname())
                            .put("photo", memberEntity.getHeader());
                }
                return R.error(ResultCode.USER_GITEE_EXIST);
            }
            return R.error(ResultCode.USER_GITEE_EXIST);
        }catch (NullPointerException e){
            return R.error(ResultCode.USER_GITEE_EXIST);
        }

    }

    /**
     * 发送短信验证码
     * @param phone
     * @return
     */
    @Override
    public R sendCode(String phone) {

        String cache = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if(StringUtils.hasText(cache)){
            if(System.currentTimeMillis() - Long.parseLong(cache.split("_")[1]) < 60000){
                return R.error(ResultCode.SMS_CODE_ERROR);
            }
        }

        String codeInt = CodeUtils.createCodeInt();
        R send = thirdPartyFeignService.send(phone, codeInt);
        if(!send.isOk()){
            return R.error();
        }
        System.out.println(codeInt);
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, codeInt + "_" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);
        return R.ok();

    }

    @Override
    public R getMemberIntegration(Long memberId) {
        MemberEntity memberEntity = baseMapper.selectById(memberId);
        return R.ok().setData(memberEntity.getIntegration());
    }

    private String setJWTRedis(String id, String name){
        String token = JwtUtils.getJwtToken(id, name);
        redisTemplate.opsForValue().set(AllConstant.MEMBER_LOGIN + id, token, 1, TimeUnit.DAYS);
        return token;
    }

}
